#ifndef BIGINT_H
#define BIGINT_H

#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <cctype>

#include "smart_vector.h"

class big_int
{
public:
   big_int();
   explicit big_int(long long digit);
   big_int(const big_int& bigint);
   explicit big_int(const std::string& str);

   big_int& operator=(const big_int& bigint);

   void swap(big_int& bigint);
   
   big_int abs() const;
   
   big_int operator-() const;
   
   bool operator<(const big_int& bigint) const;
   bool operator>(const big_int& bigint) const;
   bool operator<=(const big_int& bigint) const;
   bool operator>=(const big_int& bigint) const;
   bool operator==(const big_int& bigint) const;
   bool operator!=(const big_int& bigint) const;
   
   big_int& operator+=(const big_int& bigint);
   big_int& operator-=(const big_int& bigint);
   big_int& operator*=(const big_int& bigint);
   big_int& operator/=(const big_int& bigint);
   big_int& operator%=(const big_int& bigint);
   
   big_int operator+(const big_int& bigint) const;
   big_int operator-(const big_int& bigint) const;
   big_int operator*(const big_int& bigint) const;
   big_int operator/(const big_int& bigint) const;
   big_int operator%(const big_int& bigint) const;
   
   friend std::istream& operator>>(std::istream &is, big_int &bigint);
   friend std::ostream& operator<<(std::ostream &os, const big_int &bigint);
private:  
   typedef long long digit_t;
   
   static const digit_t BASE = 1000000000;
   static const unsigned int DIGIT_LENGTH = 9;

   int compare_to(const big_int& bigint) const;

   void normalize();
   void cut_zeroes();

   digit_t find_short_divider(const big_int& bigint) const;
   
   std::pair<big_int, big_int> divide_with_remainder(const big_int& bigint) const;
   
   big_int& operator*=(long long digit);
   big_int operator*(long long digit) const;
   
   big_int& operator<<=(int shift);
   big_int& operator>>=(int shift);

   big_int operator<<(int shift) const;
   big_int operator>>(int shift) const;
   
   smart_vector digits_;
   int shift_;
   bool negative_;
};

big_int abs(const big_int& bigint);

#endif

